home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 109_01.zip / XSDMAC.LIB < prev    next >
Text File  |  1993-06-26  |  19KB  |  954 lines

  1.     ;
  2.     ; note: BDOS should be defined by the user as the
  3.     ;    entry to CP/M (5 for normal systems 1009H for ADDS)
  4.     ;
  5.     ;    also BOOT as the entry to warmboot
  6.     ;    (0 in normal systems 1000H in ADDS)
  7.     ;
  8.     ;     -- NEW MACRO LIBRARY --
  9.     ;
  10.     ; SAVE MACRO    SAVE SPECIFIED REGISTERS
  11.     ;
  12.     ; SAVE    R1,R2,R3,R4
  13.     ;
  14.     ;     R1-R4 MAY BE B,D,H OR PSW  SAVED IN ORDER SPECIFIED
  15.     ;     IF REGS ARE OMITTED SAVE B,D AND H
  16.     ;
  17. SAVE    MACRO    R1,R2,R3,R4
  18.     IF NOT NUL R1&R2&R3&R4
  19.     IRP    R,<<R1>,<R2>,<R3>,<R4>>
  20.     IF    NUL R
  21.     EXITM
  22.     ENDIF
  23.     PUSH    R
  24.     ENDM
  25.     ELSE
  26.     IRPC    REG,BDH
  27.     PUSH    REG
  28.     ENDM
  29.     ENDIF
  30.     ENDM
  31.     ;
  32.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  33.     ;
  34.     ; RESTORE MACRO    RESTORE REGISTERS  (INVERSE OF SAVE)
  35.     ;
  36.     ; RESTORE    R1,R2,R3,R4
  37.     ;
  38.     ;     R1-R4 MAY BE B,D,H OR PSW  RESTORED IN ORDER SPECIFIED
  39.     ;     IF REGS OMITTED RESTORE H,D AND B
  40.     ;
  41. RESTORE    MACRO    R1,R2,R3,R4
  42.     IF    NOT NUL R1&R2&R3&R4
  43.     IRP    R,<<R1>,<R2>,<R3>,<R4>>
  44.     IF    NUL R
  45.     EXITM
  46.     ENDIF
  47.     POP    R
  48.     ENDM
  49.     ELSE
  50.     IRPC    REG,HDB
  51.     POP    REG
  52.     ENDM
  53.     ENDIF
  54.     ENDM
  55.     ;
  56.     ;
  57.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  58.     ;
  59.     ; CHARIN MACRO    CONSOLE INPUT TO A
  60.     ;
  61.     ; CHARIN    ADDR
  62.     ;
  63. CHARIN    MACRO    ADDR
  64.     MVI    C,1        ;;CONSOLE INPUT
  65.     CALL    BDOS        ;;CALL BDOS
  66.     IF    NOT NUL ADDR
  67.     STA    ADDR
  68.     ENDIF
  69.     ENDM
  70.     ;
  71.     ;
  72.     ; . . . . . . . . . . . . . . ... ... . .. . . . . . . . .
  73.     ;
  74.     ; CHAROUT MACRO    CONSOLE OUTPUT FROM A
  75.     ;
  76.     ; CHAROUT    ADDR
  77.     ;
  78. CHAROUT    MACRO    ADDR
  79.     IF    NOT NUL ADDR
  80.     LDA    ADDR
  81.     ENDIF
  82.     MVI    C,2        ;;CONOUT
  83.     MOV    E,A        ;;CHAR TO E
  84.     CALL    BDOS        ;;CALL BDOS
  85.     ENDM
  86.     ;
  87.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  88.     ;
  89.     ; CHARSTAT MACRO    CHECK CONSOLE STATUS
  90.     ;
  91.     ;         RETURN TRUE (FF) IF CHAR READY FALSE (0) IF NOT
  92.     ;
  93. CHARSTAT MACRO
  94.     LOCAL    EXIT
  95.     MVI    C,11
  96.     CALL    BDOS
  97.     ORA    A
  98.     JZ    EXIT
  99.     MVI    A,0FFH
  100. EXIT:    ENDM
  101.     ;
  102.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  103.     ;
  104.     ; INPUT MACRO    INPUT CHARACTER STRING FROM CONSOLE
  105.     ;
  106.     ; INPUT    ADDR,BUFLEN
  107.     ;
  108.     ;     ADDR    START OF TEXT BUFFER
  109.     ;     BUFLEN    LENGTH OF BUFFER  (DEFAULT IS 127)
  110.     ;
  111. INPUT    MACRO    ADDR,BUFLEN
  112.     MVI    C,10
  113.     IF    NOT NUL ADDR
  114.     LXI    D,ADDR        ;;SET BUFFER ADDRESS
  115.     ENDIF
  116.     IF    NOT NUL BUFLEN
  117.     MVI    A,BUFLEN    ;;SET BUFFER LENGTH
  118.     STAX    D
  119.     ELSE
  120.     MVI    A,127
  121.     STAX    D        ;;SET BUFFER DEFAULT MAXIMUM
  122.     ENDIF
  123.     CALL    BDOS        ;;BDOS ENTRY
  124.     ENDM
  125.     ;
  126.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  127.     ;
  128.     ; PRINT MACRO    PRINT A STRING ON CONSOLE
  129.     ;
  130.     ; PRINT                (CARRIAGE RETURN, LINE FEED)
  131.     ; PRINT    'LITERAL'
  132.     ; PRINT    <'LITERAL',CR,LF,'SECOND LITERAL'>
  133.     ;
  134.     ; PRINT    ADDR,$            (ASCII OUTPUT UNTIL $)
  135.     ; PRINT    ADDR,L,H        (HEX OUTPUT L CHARACTERS)
  136.     ; PRINT    ADDR,L,A        (ASCII OUTPUT L CHARACTERS)
  137.     ;
  138.     ;     LITERALS MUST BE IN SINGLE QUOTES  'LIT'
  139.     ;     IF LITERAL CONTAINS CONTROL CODES ENTIRE STRING IN <> BRACKETS
  140.     ;     MACRO ALSO ASSEMBLES
  141.     ;         CR = CARRIAGE RETURN
  142.     ;         LF = LINE FEED
  143.     ;         BEL = BELL CODE
  144.     ;
  145.     ;     MACRO ASSUMES ADDR ALREADY LOADED TO HL IF ARGUMENT OMITTED
  146.     ;
  147. PRINT    MACRO    ?STRING,LEN,TC
  148.     LOCAL    @OVER,@MESS,PLOOP,PASTCR,@CRLF
  149. CR    SET    0DH
  150. LF    SET    0AH
  151. BEL    SET    07H
  152.     IF    NUL ?STRING&LEN&TC
  153.     JMP    PASTCR
  154. @CRLF:    DB    CR
  155.     DB    LF
  156.     DB    '$'
  157. PASTCR:    LXI    D,@CRLF
  158.     MVI    C,9
  159.     CALL    BDOS
  160.     ELSE
  161.     IF    NUL LEN&TC
  162.     JMP    @OVER
  163. @MESS:    DB    ?STRING
  164.     DB    '$'
  165. @OVER:    LXI    D,@MESS
  166.     MVI    C,9
  167.     CALL    BDOS        ;;BDOS ENTRY
  168.     ELSE
  169.     IF    NUL TC
  170.     IF    NOT NUL ?STRING
  171.     LXI    D,?STRING    ;;POINTER TO STRING
  172.     ENDIF
  173.     MVI    C,9
  174.     CALL    BDOS        ;;BDOS ENTRY
  175.     ELSE
  176.     IF    NOT NUL ?STRING
  177.     LXI    H,?STRING    ;;POINTER TO STRING
  178.     ENDIF
  179.     MVI    C,LEN        ;;LENGTH OF STRING
  180. PLOOP:    PUSH    B
  181.     PUSH    H
  182.     IF    TC=H
  183.     MOV    A,M        ;;GET A BYTE
  184.     HEXOUT            ;;CONV TO HEX & OUTPUT
  185.     ELSE
  186.     MOV    E,M        ;;GET A BYTE
  187.     MVI    C,2        ;;OUT FROM E
  188.     CALL    BDOS
  189.     ENDIF
  190.     POP    H
  191.     POP    B
  192.     INX    H
  193.     DCR    C        ;;DECR LENGTH
  194.     JNZ    PLOOP        ;;CONTINUE TILL LEN 0
  195.     ENDIF
  196.     ENDIF
  197.     ENDIF
  198.     ENDM
  199.     ;
  200.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  201.     ;
  202.     ; HEXOUT MACRO    CONVERT BINARY NO AND OUTPUT TO CONSOLE
  203.     ;
  204.     ; HEXOUT    ADDR
  205.     ;
  206.     ;     NUMBER ASSUMED IN A IF NO ARGUMENT
  207.     ;
  208. HEXOUT    MACRO    ADDR
  209.     LOCAL    OUTCHR,HEXEND
  210.     JMP    HEXEND
  211. HEXPRN:    SAVE    PSW
  212.     RRC
  213.     RRC
  214.     RRC
  215.     RRC            ;;SHIFT RIGHT 4
  216.     CALL    OUTCHR
  217.     RESTORE    PSW
  218. OUTCHR: ANI    0FH        ;;MASK 4 BITS
  219.     ADI    90H        ;;ADD OFFSET
  220.     DAA            ;;DEC ADJUST
  221.     ACI    40H        ;;ADD OFFSET
  222.     DAA            ;;DEC ADJUST
  223.     MOV    E,A        ;;TO E FOR OUTPUT
  224.     MVI    C,2        ;;CONOUT
  225.     JMP    BDOS        ;;CALL BDOS
  226. HEXEND:
  227. HEXOUT    MACRO    ?ADDR
  228.     IF    NOT NUL ?ADDR
  229.     LDA    ?ADDR
  230.     ENDIF
  231.     CALL    HEXPRN
  232.     ENDM
  233.     HEXOUT    ADDR
  234.     ENDM
  235.     ;
  236.     ;
  237.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  238.     ;
  239.     ; HEXIN MACRO    CONVERT A NUMBER IN MEMORY FROM HEX TO BINARY
  240.     ;
  241.     ;         IF NO ARGUMENT MACRO ASSUMES ADDR OF HEX STRING IN HL
  242.     ;         ANSWER LEFT IN HL WITH LEAST SIGNIFICANT 8 BITS IN A
  243.     ;         CARRY SET ON ERROR. CONVERSION STOPS WHEN ZERO IS
  244.     ;         FOUND IN HEX STRING.
  245.     ;
  246. HEXIN    MACRO    ADDR
  247.     LOCAL    IN1,IN2,OVERSUB
  248.     JMP    OVERSUB
  249. @HEXIN    LXI    H,0        ;;ZERO NUMBER
  250. IN1:    LDAX    D        ;;GET A CHAR
  251.     ORA    A        ;;CHECK FOR END OF BUFFER
  252.     RZ
  253.     SUI    '0'        ;;CHECK < 0 AND CONVERT TO HEX
  254.     RC
  255.     ADI    '0'-'G'        ;;CHECK > F
  256.     RC
  257.     ADI    6
  258.     JP    IN2        ;;NO BETWEEN A AND F
  259.     ADI    7
  260.     RC
  261. IN2:    ADI    10
  262.     ORA    A        ;;CLEAR CARRY
  263.     MOV    C,A        ;;HEX DIGIT TO C
  264.     MVI    B,0        ;;ZERO TO B
  265.     DAD    H
  266.     DAD    H
  267.     DAD    H
  268.     DAD    H        ;;SHIFT LEFT 4
  269.     DAD    B        ;;ADD IN NEW DIGIT
  270.     INX    D        ;;INCR BUFFER POINTER
  271.     JMP    IN1        ;;RETURN FOR MORE INPUT
  272. OVERSUB:
  273. HEXIN    MACRO    ?ADDR
  274.     IF NOT NUL ?ADDR
  275.     LXI    D,?ADDR        ;;LOAD BUFFER ADDR
  276.     ELSE
  277.     XCHG
  278.     ENDIF
  279.     CALL    @HEXIN
  280.     MOV    A,L        ;;LEAST SIGNIFICANT 8 BITS TO A
  281.     ENDM
  282.     HEXIN    ADDR
  283.     ENDM
  284.     ;
  285.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  286.     ;
  287.     ; DECOUT MACRO    CONVERT A POSITIVE INTEGER TO DECIMAL AND OUTPUT 
  288.     ;         TO THE CONSOLE.
  289.     ;
  290.     ; DECOUT    ADDR
  291.     ;
  292.     ;     IF ADDR OMITTED, NUMBER ASSUMED TO BE IN HL, ELSE LOADED TO HL
  293.     ;     LEADING ZEROS SUPRESSED. MAXIMUM NUMBER 65,767
  294.     ;
  295. DECOUT    MACRO    ADDR
  296.     LOCAL    ENDDEC,DX
  297.     JMP    ENDDEC
  298. @DECOUT:SAVE            ;;PUSH STACK
  299.     LXI    B,-10        ;;RADIX FOR CONVERSION
  300.     LXI    D,-1        ;;THIS BECOMES NO DIVIDED BY RADIX
  301. DX    DAD    B        ;;SUBTRACT 10
  302.     INX    D
  303.     JC    DX
  304.     LXI    B,10
  305.     DAD    B        ;;ADD RADIX BACK IN ONCE
  306.     XCHG
  307.     MOV    A,H
  308.     ORA    L        ;;TEST FOR ZERO
  309.     CNZ    @DECOUT        ;;RECURSIVE CALL
  310.     MOV    A,E
  311.     ADI    '0'        ;;CONVERT FROM BCD TO HEX
  312.     MOV    E,A        ;;TO E FOR OUTPUT
  313.     CHAROUT            ;;CONSOLE OUTPUT
  314.     RESTORE            ;;POP STACK
  315.     RET
  316. ENDDEC:
  317. DECOUT    MACRO    ?ADDR
  318.     IF    NOT NUL ?ADDR
  319.     LHLD    ?ADDR
  320.     ENDIF
  321.     CALL    @DECOUT        ;;CALL THE SUBROUTINE
  322.     ENDM
  323.     DECOUT    ADDR
  324.     ENDM
  325.     ;
  326.     ;
  327.     ;
  328.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  329.     ;
  330.     ; DECIN MACRO    CONVERT A NUMBER IN MEMORY FROM ASCII TO BINARY
  331.     ;
  332.     ; DECIN    ADDR
  333.     ;
  334.     ;     ADDR POINTS TO MEMORY LOCATION OF START OF NO, IF
  335.     ;     ARG OMITTED POINTER ASSUMED LOADED TO HL
  336.     ;     MACRO RETURNS WITH CARRY SET IF ALPHABETIC CHAR FOUND
  337.     ;     CONVERSION STOPS WHEN CHAR LESS THAN ZERO IS FOUND.
  338.     ;     BINARY NUMBER IS LEFT IN HL, MAXIMUM 65,767
  339.     ;     LEAST SIGNIFICANT 8 BITS OF NUMBER IN A.
  340.     ;
  341. DECIN    MACRO    ADDR
  342.     LOCAL    DLOOP,OVERSUB
  343.     JMP    OVERSUB
  344. @DECIN:    LXI    D,0        ;;ZERO DE
  345.     XCHG            ;;ADDR POINTER TO DE, ZERO TO HL
  346. DLOOP:    LDAX    D        ;;GET A ASCII DIGIT
  347.     SUI    '0'        ;;CONVERT TO BCD AND TEST
  348.     ANA    A        ;;RESET CARRY
  349.     RM            ;;TERMINATE CONVERSION IF < ZERO
  350.     CPI    10        ;;CHECK LEGITIMATE DIGIT (0-9)
  351.     CMC            ;;COMPLEMENT CARRY
  352.     RC            ;;RET WITH CARRY SET IF ERROR
  353.     INX    D        ;;INCR ADDR POINTER
  354.     DAD    H        ;;SHIFT LEFT 1
  355.     PUSH    H        ;;SAVE RESULT
  356.     DAD    H
  357.     DAD    H        ;;SHIFT LEFT 2
  358.     POP    B        ;;NO * 2 TO B
  359.     DAD    B        ;;HL NOW CONTAINS 10*NO
  360.     MOV    C,A        ;;ADD PRODUCT TO DIGIT
  361.     MVI    B,0
  362.     DAD    B
  363.     JMP    DLOOP        ;;BACK FOR ANOTHER DIGIT
  364. OVERSUB:
  365. DECIN    MACRO    ?ADDR
  366.     IF    NOT NUL    ?ADDR
  367.     LXI    H,?ADDR
  368.     ENDIF
  369.     CALL    @DECIN        ;;CALL THE SUBROUTINE
  370.     MOV    A,L        ;;LEAST SIGNIFICANT HALF OF NO TO A
  371.     ENDM
  372.     DECIN    ADDR
  373.     ENDM
  374.     ;
  375.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  376.     ;
  377.     ; MOVE MACRO    MOVE A BLOCK FROM SOURCE TO DEST
  378.     ;
  379.     ; MOVE    SOURCE,DEST,COUNT
  380.     ;
  381.     ;     SOURCE TO HL    MACRO ASSUMES REGISTERS ALREADY
  382.     ;     DEST TO DE    LOADED IF ARG OMITTED
  383.     ;     COUNT TO BC
  384.     ;
  385. MOVE    MACRO    SOURCE,DEST,COUNT
  386.     LOCAL    OVERSUB
  387.     JMP    OVERSUB
  388. @MOVE:    MOV    A,B
  389.     ORA    C
  390.     RZ            ;;EXIT COUNT ZERO
  391.     MOV    A,M        ;;GET A BYTE
  392.     STAX    D        ;;STORE IT
  393.     INX    H
  394.     INX    D
  395.     DCX    B
  396.     JMP    @MOVE        ;;BACK TO MOVE LOOP
  397. OVERSUB:
  398. MOVE    MACRO    SRC,?D,?C
  399.     IF    NOT NUL SRC
  400.     LXI    H,SRC
  401.     ENDIF
  402.     IF    NOT NUL ?D
  403.     LXI    D,?D
  404.     ENDIF
  405.     IF    NOT NUL ?C
  406.     LXI    B,?C
  407.     ENDIF
  408.     CALL    @MOVE        ;;CALL THE MOVE SUBROUTINE
  409.     ENDM
  410.     MOVE    SOURCE,DEST,COUNT
  411.     ENDM
  412.     ;
  413.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  414.     ;
  415.     ; FILL MACRO - FILL A BLOCK OF MEMORY WITH A CONSTANT
  416.     ;
  417.     ; FILL    START,STOP,CONSTANT
  418.     ;
  419.     ;     CONSTANT OMITTED, FILL WITH 0
  420.     ;     END OMITTED, FILL ONE BYTE
  421.     ;
  422. FILL    MACRO    START,STOP,CONST
  423.     LOCAL    @FILL,BLKLEN
  424. BLKLEN    SET    STOP-START+1
  425.     LXI    H,START        ;;LOAD START ADDR
  426.     IF    NOT NUL STOP
  427.     LXI    B,BLKLEN    ;;LOAD BLOCK LENGTH
  428.     IF    NOT NUL CONST
  429.     MVI    E,CONST        ;;LOAD CONST IF NOT NULL
  430.     ELSE
  431.     MVI    E,0
  432.     ENDIF
  433. @FILL:    MOV    M,E        ;;STORE A BYTE
  434.     INX    H        ;;INCR MEMORY POINTER
  435.     DCX    B        ;;DECR COUNT
  436.     MOV    A,C        ;;TEST LIMIT
  437.     ORA    B
  438.     JNZ    @FILL        ;;CONTINUE
  439.     ELSE
  440.     IF    NUL CONST
  441.     MVI    M,0        ;;STORE A ZERO
  442.     ELSE
  443.     MVI    M,CONST        ;;STORE SINGLE BYTE
  444.     ENDIF
  445.     ENDIF
  446.     ENDM
  447.     ;
  448.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  449.     ;
  450.     ;
  451.     ; MATCH MACRO    COMPARE 2 STRINGS OF SAME LENGTH SET CARRY IF EQUAL
  452.     ;
  453.     ; MATCH    STR1,'LITERAL STRING'
  454.     ; MATCH    STR1,STR2,LENGTH
  455.     ; MATCH
  456.     ;
  457.     ;     DE POINTS TO STR1    MACRO WILL LOAD REG IF ARG
  458.     ;     HL POINTS TO STR2    PRESENT
  459.     ;     C CONTAINS LENGTH
  460.     ;
  461.     ;     SUBTRACT STR2 FROM STR1 AND SET FLAGS, ZERO INDICATES MATCH.
  462.     ;     NORMALLY THE SECOND ARG IS A LITERAL STRING AND THE LENGTH
  463.     ;     IS OMITTED. IF THE LEN ARG IS PRESENT THE SECOND STRING
  464.     ;     ARG IS ASSUMED TO BE A MEMORY ADDR. IF ALL ARGUMENTS OMITTED
  465.     ;     REGISTERS ASSUMED ALREADY LOADED.
  466.     ;
  467. MATCH    MACRO    STR1,STR2,LEN
  468.     LOCAL    OVERSUB,M1
  469.     JMP    OVERSUB
  470. @MATCH:    INR    C        ;;PRE INCREMENT COUNT (IT MIGHT BE ZERO)
  471. M1:    DCR    C        ;;DECR LENGTH COUNT
  472.     RZ            ;;RETURN IF MATCH FOUND
  473.     LDAX    D        ;;GET A BYTE FROM ONE STRING
  474.     SUB    M        ;;COMPARE WITH OTHER
  475.     RNZ            ;;RETURN
  476.     INX    H
  477.     INX    D        ;;INCR STRING POINTERS
  478.     JMP    M1        ;;TRY SOME MORE
  479. OVERSUB:
  480. MATCH    MACRO    ?STR1,?STR2,?LEN
  481.     LOCAL    LITSTR,ENDLIT
  482.     IF    NUL ?STR1&?STR2&?LEN
  483.     CALL    @MATCH
  484.     ELSE
  485.     IF    NOT NUL ?STR1
  486.     LXI    D,?STR1        ;;LOAD STRING1 POINTER
  487.     ENDIF
  488.     IF    NUL ?LEN    ;;TEST FOR LITERAL
  489.     MVI    C,ENDLIT-LITSTR    ;;LENGTH OF LITERAL STRING
  490.     LXI    H,LITSTR    ;;POINTER TO LITERAL
  491.     CALL    @MATCH
  492.     JMP    ENDLIT
  493. LITSTR:    DB    ?STR2        ;;LITERAL STRING
  494. ENDLIT:                ;;END OF STRING
  495.     ELSE
  496.     IF    NOT NUL ?STR2
  497.     LXI    H,?STR2        ;;LOAD POINTER TO STRING2
  498.     ENDIF
  499.     MVI    C,?LEN        ;;LOAD STRING LENGTH
  500.     CALL    @MATCH        ;;CALL MATCH SUBROUTINE
  501.     ENDIF
  502.     ENDIF
  503.     ENDM
  504.     MATCH    STR1,STR2,LEN
  505.     ENDM
  506.     ;
  507.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  508.     ;
  509.     ; INSTR MACRO    SEARCH STRING FOR SUBSTRING AND SET CARRY IF FOUND
  510.     ;
  511.     ; INSTR    STRING,LENGTH,SUBSTR
  512.     ;
  513.     ;     HL    POINTS TO STRING
  514.     ;     DE    POINTS TO SUBSTRING
  515.     ;     B    CONTAINS STRING LENGTH
  516.     ;     C    CONTAINS SUBSTRING LENGTH
  517.     ;
  518.     ;     MACRO RETURNS POINTER TO END OF SUBSTRING IN HL
  519.     ;
  520. INSTR    MACRO    STRING,LENGTH,SUBSTR
  521.     LOCAL    OVERSUB,S1,SSX
  522.     JMP    OVERSUB
  523. @INSTR:    MOV    A,B        ;;STRING LENGTH
  524.     SUB    C        ;;SUBTRACT SUBSTR LENGTH
  525.     CMC            ;;COMP CARRY
  526.     RNC            ;;ERROR RETURN SUBSTR > STRING
  527.     MOV    B,A        ;;NEW STRING LIMIT TO B
  528. S1:    SAVE
  529.     MATCH
  530.     RESTORE
  531.     JZ    SSX        ;;MATCH IF ZERO ON RET
  532.     ANA    A        ;;RESET CARRY
  533.     DCR    B        ;;BYTES LEFT
  534.     RM            ;;FINISHED IF MINUS, NO MATCH
  535.     INX    H        ;;INCR STRING POINTER
  536.     JMP    S1        ;;TRY AGAIN
  537. SSX:    MVI    B,0        ;;SET D TO 0
  538.     DAD    B
  539.     STC            ;;SET CARRY
  540.     RET
  541. OVERSUB:
  542. INSTR    MACRO    ?STR,?LEN,?SUBSTR
  543.     LOCAL    LITSTR,ENDLIT
  544.     IF    NOT NUL ?STR
  545.     LXI    H,?STR
  546.     ENDIF
  547.     MVI    B,?LEN
  548.     MVI    C,ENDLIT-LITSTR
  549.     LXI    D,LITSTR
  550.     CALL    @INSTR
  551.     JMP    ENDLIT
  552. LITSTR:    DB    ?SUBSTR
  553. ENDLIT:
  554.     ENDM
  555.     INSTR    STRING,LENGTH,SUBSTR
  556.     ENDM
  557.     ;
  558.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  559.     ;
  560.     ; SCAN MACRO    SCAN A STRING UNTIL A CHAR IS FOUND, SKIP BLANKS
  561.     ;         AND CONTROL CHARACTERS
  562.     ;
  563.     ;         CARRY SET IF NUMERIC, CARRY OFF IF ALPHABETIC
  564.     ;
  565.     ;
  566. SCAN    MACRO    ADDR
  567.     LOCAL    OVERSUB
  568.     JMP    OVERSUB
  569. @SCAN:    MOV    A,M        ;;GET A BYTE
  570.     CPI    21H        ;;SPACE OR LESS?
  571.     RP
  572.     INX    H        ;;INCR POINTER
  573.     JMP    @SCAN        ;;KEEP SEARCHING
  574. OVERSUB:
  575. SCAN    MACRO    ?ADDR
  576.     IF    NOT NUL ?ADDR
  577.     LXI    H,?ADDR
  578.     ENDIF
  579.     CALL    @SCAN        ;;CALL SUBROUTINE
  580.     CPI    3AH        ;;NUMBER OR ALPHA
  581.     ENDM
  582.     SCAN    ADDR
  583.     ENDM
  584.     ;
  585.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  586.     ;
  587.     ; DISKIO MACRO    EXECUTE BDOS DISK ACCESS PRIMITIVES
  588.     ;
  589.     ; DISKIO    FUNCTION,PARAMETER
  590.     ;
  591.     ;     NO    FUNCTION    ENTRY PARAM
  592.     ;
  593.     ;     12    LIFTHEAD
  594.     ;     13    INITIAL
  595.     ;     14    LOGIN        DISK NO 0 - 1
  596.     ;     15    OPEN        FCB
  597.     ;     16    CLOSE        FCB
  598.     ;     17    SEARCH        FCB
  599.     ;     18    SERNXT        FCB
  600.     ;     19    DELETE        FCB
  601.     ;     20    READ        FCB
  602.     ;     21    WRITE        FCB
  603.     ;     22    MAKE        FCB
  604.     ;     23    RENAME        FCB
  605.     ;     24    ?LOGIN
  606.     ;     25    ?DRIVE
  607.     ;     26    SETDMA        BUFFER
  608.     ;     27    ?ALLOC
  609.     ;     SEE CP/M INTERFACE GUIDE FOR DETAILED INFORMATION ON THE
  610.     ;     DISK ACCESS PRIMITIVES
  611.     ;
  612.     ; DISKIO    READ,FCB    (TYPICAL MACRO CALL)
  613.     ;
  614. DISKIO    MACRO    FUNCTION,PARAMETER
  615. LIFTHEAD    SET    12
  616. INITIAL        SET    13
  617. LOGIN        SET    14
  618. OPEN        SET    15
  619. CLOSE        SET    16
  620. SEARCH        SET    17
  621. SERNXT        SET    18
  622. DELETE        SET    19
  623. READ        SET    20
  624. WRITE        SET    21
  625. MAKE        SET    22
  626. RENAME        SET    23
  627. ?LOGIN        SET    24
  628. ?DRIVE        SET    25
  629. SETDMA        SET    26
  630. ?ALLOC        SET    27
  631.     ;
  632. ?C    SET    FUNCTION
  633.     IF    NOT NUL PARAMETER
  634.     LXI    D,PARAMETER
  635.     ENDIF
  636.     MVI    C,?C
  637.     CALL    BDOS        ;;BDOS ENTRY
  638.     ENDM
  639.     ;
  640.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  641.     ;
  642.     ; CALLBIOS MACRO    CALL BIOS ROUTINES DIRECTLY
  643.     ;
  644.     ; CALLBIOS    FUNCTION,PARAM
  645.     ;
  646. CALLBIOS    MACRO    FUNCT,PARAM
  647.     LOCAL    @CALL
  648.     ;
  649. DCOLD    SET    00H
  650. DWBOOT    SET    03H
  651. DSTAT    SET    06H
  652. DCONIN    SET    09H
  653. DCONOUT    SET    0CH        ;;CHAR IN C
  654. DLIST    SET    0FH        ;;CHAR IN C
  655. DPUNCH    SET    12H
  656. DREADER    SET    15H
  657. DHOME    SET    18H
  658. DSELDSK    SET    1BH
  659. DSETTRK    SET    1EH
  660. DSETSEC    SET    21H        ;;SECTOR NO IN C
  661. DSETDMA    SET    24H        ;;DMA ADDR IN BC
  662. DREAD    SET    27H
  663. DWRITE    SET    2AH
  664.     ;
  665. ?F    SET    FUNCT
  666.     IF    NOT NUL PARAM
  667.     MVI    C,PARAM
  668.     ENDIF
  669.     LHLD    BOOT+1        ;;ADDR OF BIOS
  670.     MVI    L,?F        ;;JUMP OFFSET
  671.     SHLD    @CALL+1        ;;MODIFY CALL ADDR
  672. @CALL:    CALL    0
  673.     ENDM
  674.     ;
  675.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  676.     ;
  677.     ; DLOAD MACRO    DOUBLE PRECISION INDEXED LOAD HL
  678.     ;
  679.     ;     LOAD (ADDR + INDX) TO HL
  680.     ;
  681. DLOAD    MACRO    ADDR,INDX
  682.     IF    NUL INDX
  683.     LHLD    ADDR
  684.     ELSE
  685.     LHLD    INDX
  686.     LXI    D,ADDR
  687.     DAD    D
  688.     MOV    E,M
  689.     INX    H
  690.     MOV    D,M
  691.     XCHG
  692.     ENDIF
  693.     ENDM
  694.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  695.     ;
  696.     ; CPHL MACRO    SUBTRACT DE FROM HL AND SET FLAGS
  697.     ;
  698. CPHL    MACRO
  699.     LOCAL    @END
  700.     MOV    A,H
  701.     CMP    D        ;;COMPARE HIGH BYTES
  702.     JNZ    @END
  703.     MOV    A,L
  704.     CMP    E        ;;COMPARE LOW BYTES
  705. @END:    ENDM
  706.     ;
  707.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  708.     ;
  709.     ; DJZ MACRO    DOUBLE PRECISION TEST HL AND JUMP ON ZERO
  710.     ;
  711. DJZ    MACRO    ADDR
  712.     MOV    A,H
  713.     ORA    L
  714.     JZ    ADDR
  715.     ENDM
  716.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  717.     ;
  718.     ; DSTORE MACRO    DOUBLE PRECISION INDEXED STORE HL
  719.     ;
  720.     ;     STORE (HL) IN (ADDR + INDX)
  721.     ;
  722. DSTORE    MACRO    ADDR,INDX
  723.     IF    NUL INDX
  724.     SHLD    ADDR
  725.     ELSE
  726.     SAVE    H
  727.     LHLD    INDX
  728.     XCHG
  729.     LXI    H,ADDR
  730.     DAD    D
  731.     RESTORE    D
  732.     MOV    M,E
  733.     INX    H
  734.     MOV    M,D
  735.     ENDIF
  736.     ENDM
  737.     ;
  738.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  739.     ;
  740.     ; INDEX MACRO    INDEX AN ADDRESS POINTER BY A CONSTANT
  741.     ;
  742.     ; INDEX    POINTER,INCR
  743.     ;
  744. INDEX    MACRO    POINTER,INCR
  745.     LHLD    POINTER
  746.     LXI    D,INCR
  747.     DAD    D        ;;DOUBLE ADD
  748.     SHLD    POINTER
  749.     ENDM
  750.     ;
  751.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . .
  752.     ;
  753.     ; FILFCB    MACRO    FILL IN THE ID FIELDS OF FCB
  754.     ;
  755.     ; FILFCB    FCB,IDSTRING
  756.     ;
  757.     ;     IDSTRING CONTAINS FILE NAME AND TYPE  (FILNAM.TYP)
  758.     ;     CARRY SET IF ERROR  (NAME TOO LONG)
  759.     ;
  760. FILFCB    MACRO    FCB,IDSTRING
  761.     LOCAL    OVERSUB,F1,F2,F3,F4,F5,F6
  762.     JMP    OVERSUB
  763. @FLFCB: MVI    M,0        ;;CLEAR FIRST BYTE OF FCB
  764.     INX    H
  765.     PUSH    H        ;;SAVE POINTER TO NAME
  766.     MVI    C,11        ;;SIZE OF ID FIELD
  767.     MVI    A,' '        ;;SPACE TO A
  768. F1:    MOV    M,A        ;;FILL NAME WITH SPACES
  769.     INX    H
  770.     DCR    C
  771.     JNZ    F1
  772.     POP    H        ;;RESTORE NAME POINTER
  773.     MVI    C,8        ;;MAXIMUM SIZE OF NAME
  774. F2:    LDAX    D        ;;GET BYTE FROM ID FIELD
  775.     CPI    ' '        ;;LEADING SPACES?
  776.     JNZ    F3
  777.     INX    D        ;;SKIP LEADING SPACES
  778.     JMP    F2
  779. F3:    LDAX    D        ;;GET ID BYTE
  780.     CPI    0        ;;ZERO END OF FIELD
  781.     RZ
  782.     CPI    ' '        ;;SPACE END OF FIELD
  783.     RZ
  784.     CPI    '.'        ;;PERIOD TYPE SEPARATOR
  785.     JZ    F4        ;;DO TYPE
  786.     MOV    M,A        ;;STORE NAME BYTE
  787.     INX    H
  788.     INX    D        ;;INCR POINTERS
  789.     DCR    C        ;;DECR MAXIMUM COUNT
  790.     JP    F3        ;;LOOP BACK
  791.     STC            ;;SET CARRY NAME TOO LARGE
  792.     RET
  793. F4:    INX    D        ;;SKIP THE PERIOD
  794.     MOV    A,C
  795.     ORA    A
  796.     JZ    F6        ;;TEST C FOR ZERO
  797. F5:    INX    H
  798.     DCR    C
  799.     JNZ    F5        ;;INDEX TO TYPE FIELD
  800. F6:    MVI    C,3        ;;SIZE OF TYPE FIELD
  801. F7:    LDAX    D        ;;GET ID BYTE
  802.     CPI    0        ;;ZERO?
  803.     RZ            ;;FINISHED
  804.     CPI    ' '        ;;SPACE?
  805.     RZ
  806.     MOV    M,A        ;;STORE TYPE BYTE
  807.     INX    H
  808.     INX    D        ;INCR POINTERS
  809.     DCR    C        ;;DECR MAX COUNT
  810.     JNZ    F7        ;;LOOP BACK
  811.     RET
  812. OVERSUB:
  813. FILFCB    MACRO    ?FCB,?ID
  814.     IF    NOT NUL    ?ID
  815.     LXI    D,?ID
  816.     ENDIF
  817.     IF    NOT NUL ?FCB
  818.     LXI    H,?FCB
  819.     ENDIF
  820.     CALL    @FLFCB
  821.     XCHG
  822.     ENDM
  823.     FILFCB    FCB,IDSTRING
  824.     ENDM
  825.     ;
  826.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  827.     ;
  828.     ; SETTRK MACRO    SET AND TEST TRACK NUMBER
  829.     ;
  830.     ;         CARRY SET IF > 76
  831.     ;
  832. SETTRK    MACRO    TRKNO
  833.     LOCAL    ENDTRK
  834.     IF    NOT NUL TRKNO
  835.     LDA    TRKNO
  836.     ENDIF
  837.     CPI    77
  838.     CMC
  839.     JC    ENDTRK
  840.     MOV    C,A        ;;TRACK NO TO C
  841.     CALLBIOS DSETTRK
  842. ENDTRK:    ENDM
  843.     ;
  844.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  845.     ;
  846.     ; SETSEC MACRO    SET AND TEST SECTOR NUMBER
  847.     ;
  848.     ;     RETURN WITH CARRY SET < 1 OR > 26
  849.     ;
  850. SETSEC    MACRO    SECNO
  851.     LOCAL    ENDSEC
  852.     IF    NOT NUL SECNO
  853.     LDA    SECNO
  854.     ENDIF
  855.     ORA    A        ;CHECK ZERO
  856.     STC
  857.     JZ    ENDSEC
  858.     CPI    27        ;CHECK > 26
  859.     CMC
  860.     JC    ENDSEC
  861.     MOV    C,A        ;MOVE TO C
  862.     CALLBIOS DSETSEC
  863. ENDSEC:    ENDM
  864.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  865.     ;
  866.     ; HALF MACRO    DIVIDES A 16 BIT NUMBER BY 2
  867.     ;
  868. HALF    MACRO    I
  869.     LOCAL    OVER
  870.     JMP    OVER
  871. @HALF:    XRA    A        ;;CLEAR CARRY
  872.     MOV    A,H
  873.     RAR            ;;SHIFT UPPER HALF
  874.     MOV    H,A
  875.     MOV    A,L
  876.     RAR            ;;SHIFT LOWER HALF
  877.     MOV    L,A
  878.     RET
  879. OVER:
  880. HALF    MACRO    ?I
  881.     IF    NOT NUL ?I
  882.     LHLD    ?I
  883.     ENDIF
  884.     CALL    @HALF
  885.     ENDM
  886.     HALF    I
  887.     ENDM
  888.     ; . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  889.     ;
  890.     ;
  891.     ;AMATCH MACRO    COMPARE 2 STRINGS OF SAME LENGTH SET CARRY IF EQUAL
  892.     ; AMBIGUOUS MATCH THAT IS '?' MATCHES ANYTHING
  893.     ;
  894.     ; MATCH    STR1,'LITERAL STRING'
  895.     ; MATCH    STR1,STR2,LENGTH
  896.     ; MATCH
  897.     ;
  898.     ; DE POINTS TO STR1    MACRO WILL LOAD REG IF ARG
  899.     ; HL POINTS TO STR2    PRESENT
  900.     ; C CONTAINS LENGTH
  901.     ;
  902.     ; SUBTRACT STR2 FROM STR1 AND SET FLAGS, ZERO INDICATES MATCH.
  903.     ; NORMALLY THE SECOND ARG IS A LITERAL STRING AND THE LENGTH
  904.     ; IS OMITTED. IF THE LEN ARG IS PRESENT THE SECOND STRING
  905.     ; ARG IS ASSUMED TO BE A MEMORY ADDR. IF ALL ARGUMENTS OMITTED
  906.     ; REGISTERS ASSUMED ALREADY LOADED.
  907.     ;
  908. AMATCH    MACRO    STR1,STR2,LEN
  909.     LOCAL    OVERSUB,M1,M2
  910.     JMP    OVERSUB
  911. @AMATCH:
  912.     INR    C    ;;PRE INCREMENT COUNT (IT MIGHT BE ZERO)
  913. M1:    DCR    C        ;;DECR LENGTH COUNT
  914.     RZ            ;;RETURN IF MATCH FOUND
  915.     MOV    A,M
  916.     CPI    '?'
  917.     JZ    M2
  918.     LDAX    D        ;;GET A BYTE FROM ONE STRING
  919.     CPI    '?'
  920.     JZ    M2
  921.     SUB    M        ;;COMPARE WITH OTHER
  922.     RNZ            ;;RETURN
  923. M2:    INX    H
  924.     INX    D        ;;INCR STRING POINTERS
  925.     JMP    M1        ;;TRY SOME MORE
  926. OVERSUB:
  927. AMATCH    MACRO    ?STR1,?STR2,?LEN
  928.     LOCAL    LITSTR,ENDLIT
  929.     IF    NUL ?STR1&?STR2&?LEN
  930.     CALL    @AMATCH
  931.     ELSE
  932.     IF    NOT NUL ?STR1
  933.     LXI    D,?STR1        ;;LOAD STRING1 POINTER
  934.     ENDIF
  935.     IF    NUL ?LEN    ;;TEST FOR LITERAL
  936.     MVI    C,ENDLIT-LITSTR    ;;LENGTH OF LITERAL STRING
  937.     LXI    H,LITSTR    ;;POINTER TO LITERAL
  938.     CALL    @AMATCH
  939.     JMP    ENDLIT
  940. LITSTR:    DB    ?STR2        ;;LITERAL STRING
  941. ENDLIT:                ;;END OF STRING
  942.     ELSE
  943.     IF    NOT NUL ?STR2
  944.     LXI    H,?STR2        ;;LOAD POINTER TO STRING2
  945.     ENDIF
  946.     MVI    C,?LEN        ;;LOAD STRING LENGTH
  947.     CALL    @AMATCH        ;;CALL MATCH SUBROUTINE
  948.     ENDIF
  949.     ENDIF
  950.     ENDM
  951.     AMATCH    STR1,STR2,LEN
  952.     ENDM
  953.     ;
  954.